<template>
  <a-modal
    class="contract-upload-image-crop-box"
    :visible="displayCropModal"
    :destroyOnClose="true"
    :footer="null"
    :maskClosable="false"
    :width="1200"
    title="图片裁剪"
    @cancel="handleModalCancel"
  >
    <div class="modal-content">
      <!-- 图片裁切插件 -->
      <VuePictureCropper
        :boxStyle="{
          width: '100%',
          height: '100%',
          backgroundColor: '#f8f8f8',
          margin: 'auto'
        }"
        :img="pic"
        :options="{
          viewMode: 1,
          dragMode: 'move',
          aspectRatio: 1,
          cropBoxResizable: false
        }"
        :presetMode="{
          mode: 'fixedSize',
          width: imgSize,
          height: imgSize
        }"
      />
    </div>
    <div class="modal-foot">
      <div class="modal-foot-contain">
        <div class="modal-foot-btn" @click="rorateImg(1)">旋转+</div>
        <div class="modal-foot-btn" @click="rorateImg(-1)">旋转-</div>
      </div>
      <div class="modal-foot-contain">
        <div class="modal-foot-btn" @click="handleModalSure">提交</div>
        <div class="modal-foot-btn" @click="handleModalCancel">取消</div>
      </div>
    </div>
  </a-modal>
</template>

<script>
import VuePictureCropper, { cropper } from 'vue-picture-cropper'
import { reactive, ref, toRefs, onMounted } from 'vue'
export default {
  components: {
    VuePictureCropper
  },
  props: {},
  setup(props, context) {
    // #region 变量
    const state = reactive({
      displayCropModal: false, // 弹框是否可见
      degreeNum: 0, // 旋转度数的次数
      onLoading: false, // 是否加载中
      imgSize: 300 // 图片固定宽高
    })
    // 上传图片
    const result = reactive({
      dataURL: '',
      blobURL: ''
    })
    const pic = ref('')
    // #endregion

    // #region 生命周期、监听、计算 函数
    onMounted(() => {})
    // #endregion

    // #region 页面操作方法
    // 生成：所选图片的裁剪画布
    const initCropInfo = file => {
      // 重置上一次的结果
      result.dataURL = ''
      result.blobURL = ''
      // 如果有多个裁剪框，也需要重置掉裁剪目标的值，避免使用同一张图片无法触发watch
      pic.value = ''
      if (!file) return
      // 转换为base64传给裁切组件
      const reader = new FileReader()
      reader.onload = () => {
        // 更新裁切弹窗的图片源
        pic.value = String(reader.result)
        // 获取加载出来的图片的最小宽或高
        let img = new Image()
        img.src = reader.result
        img.onload = function () {
          if (this.width <= this.height) {
            state.imgSize = this.width
          } else {
            state.imgSize = this.height
          }
        }
        // cropper.reset() // 重置默认的裁切区域
        // 显示裁切弹窗
        state.displayCropModal = true
      }
      reader.readAsDataURL(file)
    }
    // 操作：旋转
    const rorateImg = async num => {
      state.degreeNum += num
      cropper.rotateTo((state.degreeNum % 4) * 90) // 设置旋转一次的幅度为 90°
    }
    // 操作：裁剪框-确定
    const handleModalSure = async () => {
      if (state.onLoading) return
      state.onLoading = true
      // 获取生成的base64图片地址
      const base64 = cropper.getDataURL()
      // 获取生成的blob文件信息
      const blob = await cropper.getBlob()
      // 获取生成的file文件信息
      const file = await cropper.getFile({
        // fileName: '测试文件名，可不传'
      })
      // console.log({ base64, blob, file })
      // 把base64赋给结果展示区
      result.dataURL = base64
      try {
        result.blobURL = URL.createObjectURL(blob)
      } catch (e) {
        result.blobURL = ''
      }
      context.emit('handleModalSure', { base64, blob, file })
      state.displayCropModal = false
      state.onLoading = false
    }
    // 操作：裁剪框-取消
    const handleModalCancel = () => {
      context.emit('handleModalCancel')
      state.displayCropModal = false
    }
    // #endregion

    return {
      ...toRefs(state),
      initCropInfo,
      result,
      pic,
      rorateImg,
      handleModalSure,
      handleModalCancel
    }
  }
}
</script>

<style lang="less">
.contract-upload-image-crop-box {
  position: relative;
  top: calc(50% - 40vh);
  .ant-modal-content {
    .ant-modal-body {
      width: 100%;
      height: calc(80vh - 55px);
      overflow: hidden;
      .modal-title {
        width: 100%;
        margin-top: 18px; // 42 - 24
        margin-bottom: 40px;
        text-align: center;
        font-size: 36px;
        font-weight: bold;
        color: #333;
      }
      .modal-content {
        height: calc(100% - 40px - 30px);
        width: 100%;
      }
      .modal-foot {
        margin-top: 30px;
        display: flex;
        justify-content: space-between;
        align-items: center;
        .modal-foot-contain {
          display: flex;
          align-items: center;
        }
        .modal-foot-btn {
          width: 112px;
          height: 40px;
          margin: 0 8px;
          border-radius: 6px;
          line-height: 40px;
          text-align: center;
          font-size: 16px;
          font-weight: bold;
          color: #333;
          box-shadow: 0px 3px 6px 1px rgba(0, 0, 0, 0.16);
          cursor: pointer;
          &:hover {
            box-shadow: 0px 1px 2px 1px rgba(0, 0, 0, 0.16);
          }
        }
      }
    }
  }
}
</style>

<style lang="less" scoped></style>
